<?php

namespace Sharks\Core\Support\Base;

use InvalidArgumentException;

/**
 * FIXME: 动态参数是php5.6+以后的特性
 * 
 * 参数检查类，用于方法或执行过程前的参数检查，当参数不满足某一条件时，抛出InvalidArgument异常。
 * 示例:
 *  $age = 11;
 * 	Precondition::check($age > 10); // true
 *  Precondition::check($age < 1); // false 将抛出异常
 *  
 *  $foo = null;
 *  Precondition::checkNotNull($foo); // is null
 *  
 *  $foo = [];
 *  Precondition::checkNotEmpty($foo); // is empty
 *  
 *  $foo = ['bar' => 1];
 *  Precondition::checkInArray($foo, 'bar');//in array
 *  
 * 消息替位符格式请参考函数sprintf的消息格式
 */
class Precondition {

	const DEFAULT_MSG = 'Invalid Arguments';

	/**
	 * 检查表达式或值是否正确，如果为false，抛出异常
	 *  
	 * @param  [type] $expression 表达式的值
	 * @param  [type] $msg        如果表达式的值为假，抛出异常的消息。如果消息为空，则使用Precondition默认消息
	 * @param  [type] $msgArgs    如果表达式的值为假，将使用为消息的点位符参数，详见sprintf方法。
	 * @return [type]             [description]
	 */
	public static function check($expression, $msg = null, ...$msgArgs) {
		if (!$expression) {
			if (empty($msg)) {
				throw new InvalidArgumentException(self::DEFAULT_MSG);
			}
			throw new InvalidArgumentException(vsprintf($msg, $msgArgs));
		}

	}

	/**
	 * 检查传入对象是否为Null，如果为Null，抛出异常
	 * 
	 * @param  [type] $obj     [description]
	 * @param  [type] $msg     [description]
	 * @param  [type] $msgArgs [description]
	 * @return [type]          [description]
	 */
	public static function checkNotNull($obj, $msg = null, ...$msgArgs) {
		return self::check(!is_null($obj), $msg, $msgArgs);
	}

	/**
	 * 检查传入对象是否为空，表示为: null, 空字符串''。
	 * 若变量不存在则抛出异常
	 *  若变量存在且其值为""、0、"0"、NULL、、FALSE、 array()、var $var; 以及没有任何属性的对象，则抛出异常
	 *
	 * 函数empty说明
	 * empty不能判断字符串为空字符串
	 * 	格式：bool empty ( mixed var )
	 *  功能：检查一个变量是否为空
	 *  返回值：
	 *  若变量不存在则返回 TRUE
	 *  若变量存在且其值为""、0、"0"、NULL、、FALSE、 array()、var $var; 以及没有任何属性的对象，则返回 TURE
	 *  若变量存在且值不为""、0、"0"、NULL、、FALSE、 array()、var $var; 以及没有任何属性的对象，则返回 FALSE
	 *  
	 * @param  [type] $obj     [description]
	 * @param  [type] $msg     [description]
	 * @param  [type] $msgArgs [description]
	 * @return [type]          [description]
	 */
	public static function checkNotEmpty($obj, $msg = null, ...$msgArgs) {
		self::checkNotNull($obj, $msg, $msgArgs);//检查是否为Null
		if (is_string($obj) && trim($obj) == '') {
			if (empty($msg)) {
				throw new InvalidArgumentException(self::DEFAULT_MSG);
			}
			throw new InvalidArgumentException(vsprintf($msg, $msgArgs));
		}
		self::check(!empty($obj), $msg, $msgArgs);//检查是否为Empty

	}

	/**
	 * 数组中是否存在指定的索引值
	 * 
	 * @param array $array
	 * @param mixed $key
	 * @param string $msg
	 * @param mixed ...$msgArgs
	 * @throws InvalidArgumentException
	 */
	public static function checkInArray(array $array, $key, $msg = null, ...$msgArgs) {
		self::checkNotEmpty($array, $msg, $msgArgs);
		if (!in_array($key, $array) && !array_key_exists($key, $array)) {
			
			if (empty($msg)) {
				throw new InvalidArgumentException(self::DEFAULT_MSG);
			}
			throw new InvalidArgumentException(vsprintf($msg, $msgArgs));
		}
	}
}